using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace ICP_MS.Plugin.Experiment;

public class SemiCalculator
{
	private static SemiCalculator calculator;

	private SemiCurve semiCurve = new SemiCurve();

	private List<SemiIsotope> rsfIsotopes = new List<SemiIsotope>();

	private List<SemiIsotope> semiIsotopes = new List<SemiIsotope>();

	public SemiCurve Curve => semiCurve;

	public List<SemiIsotope> RSFIsotopes => rsfIsotopes;

	public List<SemiIsotope> SemiIsotopes => semiIsotopes;

	public static SemiCalculator Calculator
	{
		get
		{
			if (calculator == null)
			{
				calculator = new SemiCalculator();
			}
			return calculator;
		}
	}

	public void Sort()
	{
		rsfIsotopes.Sort((SemiIsotope s1, SemiIsotope s2) => s1.Mass.CompareTo(s2.Mass));
	}

	public void CalculateCurve()
	{
		List<double> x = new List<double>();
		List<double> y = new List<double>();
		foreach (SemiIsotope isotope in semiIsotopes)
		{
			if (isotope.Correct)
			{
				x.Add(isotope.Mass);
				y.Add(isotope.Factor);
			}
		}
		if (x.Count >= 4)
		{
			double[] result = LSFit.Polynomial(x.ToArray(), y.ToArray(), 2);
			semiCurve.a0 = result[0];
			semiCurve.a1 = result[1];
			semiCurve.a2 = result[2];
			double[] yy = new double[y.Count];
			for (int i = 0; i < y.Count; i++)
			{
				yy[i] = CalculateFactor(x[i]);
			}
			semiCurve.R = LSFit.PearsonR(y.ToArray(), yy);
		}
	}

	private double CalculateFactor(double mass)
	{
		return semiCurve.a0 + semiCurve.a1 * mass + semiCurve.a2 * mass * mass;
	}

	public double Calculate(double mass, double intensity, string symbol)
	{
		SemiIsotope rsf = rsfIsotopes.Find((SemiIsotope r) => r.Mass == mass && r.Symbol == symbol);
		if (rsf != null)
		{
			return intensity / (rsf.CaliFactor / rsf.RSF);
		}
		return double.NaN;
	}

	public void Load()
	{
		string filename1 = Application.StartupPath + "\\iMassConfig\\SemiQuant.xml";
		try
		{
			using FileStream fs = new FileStream(filename1, FileMode.Open, FileAccess.Read);
			XmlSerializer xml = new XmlSerializer(typeof(List<SemiIsotope>));
			if (xml.Deserialize(fs) is List<SemiIsotope> semis)
			{
				rsfIsotopes = semis;
			}
		}
		catch (Exception)
		{
		}
	}

	public void Save()
	{
		string filename1 = Application.StartupPath + "\\iMassConfig\\SemiQuant.xml";
		try
		{
			using FileStream fs = new FileStream(filename1, FileMode.Create, FileAccess.Write);
			XmlSerializer xml = new XmlSerializer(typeof(List<SemiIsotope>));
			xml.Serialize(fs, rsfIsotopes);
		}
		catch (Exception)
		{
		}
	}
}
